home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / GOPINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-28  |  8.4 KB  |  252 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #ifdef MSDOS
  3. #include <dpmi.h>
  4. #include <go32.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/exceptn.h>
  8.  
  9. /*lint -save -e717 */
  10.  
  11. #if !defined(_lint)
  12. static char rcsid[] OPTIONAL = "$Id: gopint.c,v 1.4 1996/12/29 02:47:22 root Exp root $";
  13. #endif
  14.  
  15. /* We enter with only CS known, and SS on a locked 4K stack which
  16.    is *NOT* our SS.  We must set up everthing, including a stack swap,
  17.    then restore it the way we found it.   C. Sandmann 4-93 */
  18.  
  19. /*
  20.  * NOTE: we now store some information in the stack interrupt stack
  21.  *    long 0 = flags    (currently bit 0 = this stack was malloc()ed)
  22.  *    long 1 = block count (if non-zero, users's function won't be called)
  23.  *    long 2 = count of how many times this wrapper has been hit
  24.  *            (note: count includes times when we're recursively
  25.  *                             called and don't call the user's function)
  26.  */
  27.  
  28. #define    STACK_WAS_MALLOCED    (1 << 0)
  29.  
  30. #define    FILL    0x00
  31.  
  32. static unsigned char wrapper_intcommon[] = {
  33. /* 00 */ 0x1e,                /*     push ds                  */
  34. /* 01 */ 0x06,                /*     push es            */
  35. /* 02 */ 0x0f, 0xa0,            /*     push fs                  */
  36. /* 04 */ 0x0f, 0xa8,            /*     push gs                  */
  37. /* 06 */ 0x60,                /*     pusha                    */
  38. /* 07 */ 0x66, 0xb8,            /*     mov ax,            */
  39. /* 09 */ FILL, FILL,            /*         _our_selector    */
  40. /* 0B */ 0x8e, 0xd8,            /*     mov ds, ax               */
  41. /* 0D */ 0xff, 0x05,             /*     incl            */
  42. /* 0F */ FILL, FILL, FILL, FILL,    /*        _call_count        */
  43. /* 13 */ 0x83, 0x3d,            /*     cmpl            */
  44. /* 15 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  45. /* 19 */ 0x00,                /*         $0            */
  46. /* 1A */ 0x75,                /*     jne            */
  47. /* 1B */ 0x2F,                /*         bypass        */
  48. /* 1C */ 0xc6, 0x05,            /*     movb            */
  49. /* 1E */ FILL, FILL, FILL, FILL,    /*         _in_this_handler     */
  50. /* 22 */ 0x01,                /*         $1            */
  51. /* 23 */ 0x8e, 0xc0,            /*     mov es, ax               */
  52. /* 25 */ 0x8e, 0xe0,            /*     mov fs, ax               */
  53. /* 27 */ 0x8e, 0xe8,            /*     mov gs, ax               */
  54. /* 29 */ 0xbb,                /*     mov ebx,            */
  55. /* 2A */ FILL, FILL, FILL, FILL,    /*         _local_stack        */
  56. /* 2E */ 0xfc,                /*     cld                      */
  57. /* 2F */ 0x89, 0xe1,            /*     mov ecx, esp             */
  58. /* 31 */ 0x8c, 0xd2,            /*     mov dx, ss               */
  59. /* 33 */ 0x8e, 0xd0,            /*     mov ss, ax               */
  60. /* 35 */ 0x89, 0xdc,            /*     mov esp, ebx             */
  61. /* 37 */ 0x52,                /*     push edx                 */
  62. /* 38 */ 0x51,                /*     push ecx                 */
  63. /* 39 */ 0xe8,                /*     call            */
  64. /* 3A */ FILL, FILL, FILL, FILL,    /*         _rmih        */
  65. /* 3E */ 0x58,                /*     pop eax                     */
  66. /* 3F */ 0x5b,                /*     pop ebx                     */
  67. /* 40 */ 0x8e, 0xd3,            /*     mov ss, bx               */
  68. /* 42 */ 0x89, 0xc4,            /*     mov esp, eax             */
  69. /* 44 */ 0xc6, 0x05,            /*     movb            */
  70. /* 46 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  71. /* 4A */ 0x00,                /*         $0            */
  72. /* 4B */ 0x61,                /* bypass:  popa        */
  73. /* 4C */ 0x90,                /*     nop            */
  74. /* 4D */ 0x0f, 0xa9,            /*     pop gs                   */
  75. /* 4F */ 0x0f, 0xa1,            /*     pop fs                   */
  76. /* 51 */ 0x07,                /*     pop es                   */
  77. /* 52 */ 0x1f                /*     pop ds                   */
  78. };
  79.  
  80. static unsigned char wrapper_intiret[] = {
  81. /* 53 */ 0xcf,                /*     iret                     */
  82. };
  83.  
  84. static unsigned char wrapper_intchain[] = {
  85. /* 53 */ 0x2e, 0xff, 0x2d,        /*     jmp     cs:         */
  86. /* 56 */ FILL, FILL, FILL, FILL,    /*     [_old_int+39]         */
  87. /* 5A */ 0xcf,                /*     iret                     */
  88. /* 5B */ FILL, FILL, FILL, FILL,    /*     old_address         */
  89. /* 5F */ FILL, FILL,            /*     old_segment         */
  90. };
  91.  
  92. unsigned long _go32_interrupt_stack_size = 32256;
  93.  
  94. int _go32_dpmi_lock_data( void *lockaddr, unsigned long locksize )
  95.     {
  96.     unsigned long baseaddr;
  97.     __dpmi_meminfo memregion;
  98.  
  99.     if( __dpmi_get_segment_base_address( _go32_my_ds(), &baseaddr) == -1 ) return( -1 );
  100.  
  101.     memset( &memregion, 0, sizeof(memregion) );
  102.  
  103.     memregion.address = baseaddr + (unsigned long) lockaddr;
  104.     memregion.size    = locksize;
  105.  
  106.     if( __dpmi_lock_linear_region( &memregion ) == -1 ) return( -1 );
  107.  
  108.     return( 0 );
  109.     }
  110.  
  111. int _go32_dpmi_lock_code( void *lockaddr, unsigned long locksize )
  112.     {
  113.     unsigned long baseaddr;
  114.     __dpmi_meminfo memregion;
  115.  
  116.     if( __dpmi_get_segment_base_address( _go32_my_cs(), &baseaddr) == -1 ) return( -1 );
  117.  
  118.     memset( &memregion, 0, sizeof(memregion) );
  119.  
  120.     memregion.address = baseaddr + (unsigned long) lockaddr;
  121.     memregion.size    = locksize;
  122.  
  123.     if( __dpmi_lock_linear_region( &memregion ) == -1 ) return( -1 );
  124.  
  125.     return( 0 );
  126.     }
  127.  
  128. static int _go32_dpmi_chain_protected_mode_interrupt_vector_with_stack(int vector,
  129.     _go32_dpmi_seginfo *info, unsigned char *stack, unsigned long stack_length)
  130. {
  131.   unsigned char *wrapper;
  132.   __dpmi_paddr pm_int;
  133.  
  134. #define    CHECK_STACK()                            \
  135.   if ((stack_length && stack_length < 512) ||                \
  136.         (!stack_length && _go32_interrupt_stack_size < 512))    \
  137.     return 0x8015
  138.  
  139.   CHECK_STACK();
  140.  
  141.   wrapper = (unsigned char *)malloc(sizeof(wrapper_intcommon) +
  142.                              sizeof(wrapper_intchain));
  143.   if (wrapper == 0)
  144.     return 0x8015;
  145.  
  146.   if( _go32_dpmi_lock_data( wrapper,
  147.     sizeof(wrapper_intcommon) + sizeof(wrapper_intchain)) ) return 0x8015;
  148.  
  149. #define    MALLOC_STACK()                    \
  150.   do {                            \
  151.       if (!stack_length) {                \
  152.       stack_length = _go32_interrupt_stack_size;    \
  153.       stack = (unsigned char *)malloc(stack_length);\
  154.       if (stack == 0) {                \
  155.         free(wrapper);                \
  156.         return 0x8015;                \
  157.       }                        \
  158.           if( _go32_dpmi_lock_data( stack,              \
  159.             stack_length) ) return 0x8015;              \
  160.       ((long *)stack)[0] = STACK_WAS_MALLOCED;    \
  161.       } else                        \
  162.       ((long *)stack)[0] = 0;            \
  163.       ((long *)stack)[1] = 0;                \
  164.       ((long *)stack)[2] = 0;                \
  165.   } while (0)    
  166.  
  167.   MALLOC_STACK();
  168.  
  169.   (void) __dpmi_get_protected_mode_interrupt_vector(vector, &pm_int);
  170.  
  171.   memcpy(wrapper, wrapper_intcommon, sizeof(wrapper_intcommon));
  172.   memcpy(wrapper+sizeof(wrapper_intcommon), wrapper_intchain,
  173.                              sizeof(wrapper_intchain));
  174.  
  175. #define    FILL_INT_WRAPPER()                        \
  176.   *(unsigned short *)(wrapper+0x09) = __djgpp_ds_alias;            \
  177.   *(long  *)(wrapper+0x0F) = (long) stack + 8;                \
  178.   *(long  *)(wrapper+0x15) = (long) stack + 4;                \
  179.   *(long  *)(wrapper+0x1E) = (long) stack + 4;                \
  180.   *(long  *)(wrapper+0x2A) = (long) stack + (long) stack_length;    \
  181.   *(long  *)(wrapper+0x3A) = (long) info->pm_offset - ((long)wrapper + 0x3E);    \
  182.   *(long  *)(wrapper+0x46) = (long) stack + 4
  183.  
  184.   FILL_INT_WRAPPER();
  185.  
  186.   *(long  *)(wrapper+0x56) = (long) wrapper + 0x5B;
  187.   *(unsigned long  *)(wrapper+0x5B) = pm_int.offset32;
  188.   *(unsigned short *)(wrapper+0x5F) = pm_int.selector;
  189.  
  190.   pm_int.offset32 = (unsigned long) wrapper;
  191.   pm_int.selector = (unsigned short) _my_cs();
  192.   (void) __dpmi_set_protected_mode_interrupt_vector(vector, &pm_int);
  193.   return 0;
  194. }
  195.  
  196. int _go32_dpmi_chain_protected_mode_interrupt_vector(int vector,
  197.                               _go32_dpmi_seginfo *info)
  198. {
  199.     return _go32_dpmi_chain_protected_mode_interrupt_vector_with_stack(vector,
  200.                          info, (unsigned char *) 0, 0);
  201. }
  202.  
  203. static int _go32_dpmi_allocate_iret_wrapper_with_stack(_go32_dpmi_seginfo *info,
  204.                   unsigned char *stack, unsigned long stack_length)
  205. {
  206.   unsigned char *wrapper;
  207.  
  208.   CHECK_STACK();
  209.  
  210.   wrapper = (unsigned char *)malloc(sizeof(wrapper_intcommon) +
  211.                              sizeof(wrapper_intiret));
  212.  
  213.   if (wrapper == 0)
  214.     return 0x8015;
  215.  
  216.   if( _go32_dpmi_lock_data( wrapper,
  217.     sizeof(wrapper_intcommon) + sizeof(wrapper_intiret)) ) return 0x8015;
  218.  
  219.   MALLOC_STACK();
  220.  
  221.   memcpy(wrapper, wrapper_intcommon, sizeof(wrapper_intcommon));
  222.   memcpy(wrapper+sizeof(wrapper_intcommon), wrapper_intiret,
  223.      sizeof(wrapper_intiret));
  224.  
  225.   FILL_INT_WRAPPER();
  226.  
  227.   info->pm_offset = (unsigned long) wrapper;
  228.   info->pm_selector = (unsigned short) _my_cs();
  229.   return 0;
  230. }
  231.  
  232. int _go32_dpmi_allocate_iret_wrapper(_go32_dpmi_seginfo *info)
  233. {
  234.     return _go32_dpmi_allocate_iret_wrapper_with_stack(info,
  235.                             (unsigned char *)0, 0);
  236. }
  237.  
  238. int _go32_dpmi_free_iret_wrapper(_go32_dpmi_seginfo *info)
  239. {
  240.   char *stack;
  241.   char *wrapper = (char *)info->pm_offset;
  242.  
  243.   stack = (char *)(*(long *)(wrapper+0x0F) - 8);
  244.   if (*(long *) stack & STACK_WAS_MALLOCED)
  245.       free(stack);
  246.   free(wrapper);
  247.   return 0;
  248. }
  249.  
  250. /*lint -restore */
  251. #endif
  252.